﻿# 
#
# THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
# ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
# PARTICULAR PURPOSE.
#


################################
#CLIENT SERVICE

#region Test-Client
function Test-Client {
	<# 
		.Synopsis
			Checks the client [network] connectivity and service status.
		
		.Description
			Retrieve the BESClient service and validate it's status.
		
		.Parameter HostName
			Hostname, FQDN, or IP address of client to be tested.
		
		.Parameter List
			List of computers to perform the Test-Client on.
		
		.Parameter skipServiceTest
			This will allow you to skip the Service test when validating the TEM Client service.
			
		.Parameter skipHostValidation
			This switch will speed up the confirmation process by skipping the host network connectivity check.
		
		.Example
			Test-Client DanielServer
			C:\PS>Test-Client -HostName DanielServer
			
			C:\PS>Test-Client -h DanielServer
			
			Description
			-----------
			Tests the client service.

		.Example
			Test-Client DanielServer -s
			C:\PS>Test-Client DanielServer -skipServiceTest
			
			Description
			-----------
			This allows you to skip the service test.
		
		.Example
			"DanielServer" | Test-Client
			Description
			-----------
			Receives input from the pipeline for testing if a client is functioning properly.
			
		.Example
			Test-Client -l hostlist.txt
			C:\PS>Test-Client -List hostlist.txt
			
			Description
			-----------
			Loops thru the incoming list and calls the Test-Client on it.
			
		.OUTPUTS
			System.Boolean
			System.Object
		
		.NOTES
			NAME:       Test-Client
			AUTHOR:     Daniel H Moran
			LASTEDIT:   04/18/2011
			#Requires   -Version 2.0
	#>
	
	[Cmdletbinding()]
    param(
		[Parameter(
			Position = 0,
			ValueFromPipeline = $true,
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Hostname or IP address of the client to be tested."
			)] [Alias("h")]
		[string]$HostName = $Env:ComputerName,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Client List to be tested."
			)] [Alias("l")] [validateScript({ Test-Path $_ })]
		[string]$List,
		
		[Parameter(
			HelpMessage = "This will allow you to skip the Service test when validating the TEM Client service."
		)] [Alias("s")]
		[switch]$skipServiceTest,
		
		[Parameter(
			HelpMessage = "Skip Host Validation Part."
			)]
		[switch]$skipHostValidation		
		)
   
	
	begin {
		$Service_success = $false
		
		if ($List -ne "") {
			$ret = @()
		}
    } #begin
    
    process {
		if ($List -ne "") {
			Write-Verbose "[Test-Client] :: List = $List"
			
			#now read whole file and search each of them for our problems...
			$hostlist = (Get-Content -Path $List)
			#$num = ($hostlist | Measure-Object).count
			#Write-Host "List contains $num hosts."

			$successCount = 0
			$failureCount = 0
			foreach($HostName in $hostlist)
			{	
				if ($HostName.trim() -ne "") {
					Write-Verbose "[Test-Client] :: Processing $HostName"
					if ($skipServiceTest) {
						Write-Verbose "[Test-Client] :: Calling Test-Client -HostName $HostName -skipServiceTest"
						$ct = Test-Client -HostName $HostName -skipServiceTest
					} else {
						Write-Verbose "[Test-Client] :: Calling Test-Client -HostName $HostName"
						$ct = Test-Client -HostName $HostName
					}
					
					if ($ct.ErrorMessage -eq $null) {
						$successCount++
						Write-Verbose "[Test-Client] :: Working Properly" 
					} else {
						$failureCount++
						Write-Verbose "[Test-Client] :: Not Working Properly"
					}
					
					$ret += $ct
				}
			}
			
			Write-Verbose "[Test-Client] :: Hosts Working Properly:  $successCount"
			Write-Verbose "[Test-Client] :: Hosts Not Working Properly:  $failureCount"
			
	
		} else {
			Write-Verbose "[Test-Client] :: Validating Host Exists and is Accessable"
			[bool]$DoIT = $true
			if (!$SkipHostValidation) { $DoIT = (Test-Host -HostName $HostName -skipShareTest) }
			if ($DoIT) {
		
			
				#Test Service
				if (!$skipServiceTest) {
					try {
						Write-Verbose "[Test-Client] :: Retrieving Service"
						
						$service = Get-Service -ComputerName $HostName -Name "BESClient" -ErrorAction SilentlyContinue
						
						#try a different way if wmi doesn't work...
						if ($service -eq $null) {
							Write-Verbose "[Test-Client] :: Failed to retrieve Service, trying WMI alternative..."
							$service = Get-WmiObject -ErrorAction SilentlyContinue -ComputerName $HostName -Class Win32_Service | Where {$_.DisplayName -eq "BESClient"} 
						}
						
						if ($service.Status -eq "Running") {
							$Service_success = $true
							Write-Verbose "[Test-Client] :: Service Running thus Service Test Successful"
						} elseif ($service -eq $null) {
							$Service_success = $false 
							Write-Verbose "[Test-Client] :: Service does not exist thus Service Test Unsuccessful"
						} else { 
							$Service_success = $false 
							Write-Verbose "[Test-Client] :: Service Not Running thus Service Test Unsuccessful"
						}
					} catch {
						$Service_success = $false
						Write-Verbose "[Test-Client] :: Failed to retrieve object thus Service Test Failed"
					}
				}
			
			
			} else {
				$Service_success = $false
				Write-Verbose "[Test-Client] :: Unable to Access Host"
			}
		} #List
	} #process

	
	end {
		if ($List -eq "") {
			return ($Service_success)
		} else { return $ret }
	} #end
} 
#export-modulemember -function Test-Client
#endregion


#region Read-Client
function Read-Client {
<# 
		.Synopsis
			Reads various statistics about the client, the service, and general settings.
			
		.Description
			The HostName is IP resolved, and [network] connectivity is checked.  Then we 
			pull in the Masthead and process for vital information.  We then run a 
			Test-Client on HostName to pull Service status.  Lastly we pull a few client 
			settings for __RelayServer1/2.
			
		.Parameter HostName
			HostName of the TEM Client to be queried.
			
		.Parameter List
			List of HostNames to be Queried.
			
		.Example
			Read-Client
			Description
			-----------
			Reads the client status on the localhost.
		
		.Example
			Read-Client DanielPC
			C:\PS>Read-Client -h DanielPC
			
			C:\PS>Read-Client -HostName DanielPC
			
			Description
			-----------
			Reads the client status on the DanielPC.
		
			
		.OUTPUTS
			System.Object
		
		.NOTES
			NAME:       Read-Client
			AUTHOR:     Daniel H Moran
			LASTEDIT:   04/20/2011
			#Requires   -Version 2.0
	#>
	
	[Cmdletbinding()]
    param(
		[Parameter(
			Position = 0,
			ValueFromPipeline = $true,
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Hostname or IP address of the relay to be queried."
			)] [Alias("h")]
		[string]$HostName = $Env:ComputerName,
		
		[Parameter(
			HelpMessage = "Relay List to pull from."
			)] [Alias("l")] [validateScript({ Test-Path $_ })]
		[string]$List
		)
		
	begin {
		if ($List -ne "") {
			$ret = @()
		} else { 
			$ret = "" | Select HostName,IP,Infrastructure,Node6432,Service,CurRelay,Relay1,Relay2,ErrorMessage
			$ret.HostName = $null
			$ret.IP = $null
			$ret.Infrastructure = $null
			$ret.Node6432 = $null
			$ret.Service = $null
			$ret.CurRelay = $null
			$ret.Relay1 = $null
			$ret.Relay2 = $null
			$ret.ErrorMessage = $null
		}
	} #end begin
	
	
	process {
		if ($List -ne "") {
			Write-Verbose "[Read-Client] :: List = $List"
			
			#now read whole file and search each of them for our problems...
			$hostlist = (Get-Content -Path $List)
			#$num = ($hostlist | Measure-Object).count
			#Write-Host "List contains $num hosts."

			foreach($HostName in $hostlist)
			{	
				if ($HostName.trim() -ne "") {
					Write-Verbose "[Read-Client] :: Processing $HostName"
					Write-Verbose "[Read-Client] :: Calling Read-Client -HostName $HostName"
					
					#Write-Host "----------------"
					#Write-Host "Hostname:  $HostName"
					$clt = Read-Client -HostName $HostName
													
					if ($clt.ErrorMessage -eq $null) {
						$successCount++
						Write-Verbose "[Read-Client] :: Successfully Read Endpoint"
					} else {
						$failureCount++
						Write-Verbose "[Read-Client] :: Failed to Read Endpoint"
					}

					$ret += $clt
				}
			}
			
			
		} else {
			#if user passed in IP address instead of dns hsotname, then convert appropriately.
			
			if ($HostName -match "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}") {
				Write-Verbose "[Read-Client] :: User Passed in IP Address, resolve DNS HostName"
				$ret.IP = $HostName
				
				try {
					$HostEntry = [System.Net.Dns]::GetHostEntry($HostName)
					if ($HostEntry -ne $null) {
						$ret.HostName = $HostEntry.HostName
					}
				} catch { }
			} else {
				Write-Verbose "[Read-Client] :: User Passed in DNS HostName, resolve IP Address"
				$ret.HostName = $HostName
				
				try {
					$HostEntry = [System.Net.Dns]::GetHostEntry($HostName)
					if ($HostEntry -ne $null) {
						$ret.IP = $HostEntry.AddressList[0].IPAddressToString
					}
				} catch { }
			}
			
			if (Test-Host -HostName $HostName) {
				Write-Verbose "[Read-Client] :: Successfully Validated Host"
			
				Write-Verbose "[Read-Client] :: Pulling Relay Configuration"
				#Write-Host "Computer:`t" -ForegroundColor Gray -NoNewline
				#Write-Host $HostName -ForegroundColor Cyan
				
				Write-Verbose "[Read-Client] :: Calling Get-Masthead -HostName $HostName"
				#Write-Host "TEMRoot:`t" -ForegroundColor Gray -NoNewline
				$mh = Get-Masthead -HostName $HostName -SkipHostValidation
				$ret.Infrastructure = $mh.Infrastructure
				if ($mh.ErrorMessage -eq $null) { 
				#	$imsg = $mh.Infrastructure.Name + " (" + $mh.Infrastructure.TEMRoot + ":" + $mh.Infrastructure.TEMPort + ")"
				#	Write-Host $imsg -ForegroundColor White
					Write-Verbose "[Read-Client] :: Successfully retrieved Masthead"
				} else {
				#	$imsg = $mh.ErrorMessage
				#	Write-Host $imsg -ForegroundColor Red
					Write-Verbose "[Read-Client] :: Failed to retrieve Masthead" 
				}
				
				
				
				#piggyback on the previous call to determine if a machine is 64bit or not...
				#Write-Host "Client:`t`t" -ForegroundColor Gray -NoNewline
				if ($mh.ErrorMessage -eq $null) {
					if ($mh.RemotePath.contains("(x86)") -or $mh.LocalPath.contains("(x86)")) {
						#Write-Host "64bit" -ForegroundColor White
						$ret.Node6432 = "x64"
					} else {
						#Write-Host "32bit" -ForegroundColor White
						$ret.Node6432 = "x86"
					}
				} else {
					#Write-Host $mh.ErrorMessage -ForegroundColor Red
					$ret.Node6432 = "Error:  Unable to determine."
				}
				
				
				#Write-Host "Service:`t" -ForegroundColor Gray -NoNewline
				if (Test-Client -HostName $HostName -SkipHostValidation) {
					#Write-Host "Working Properly" -ForegroundColor Green
					$ret.Service = "Working Properly"
				} else { 
					#Write-Host "Not Working Properly or Host Not Accessible" -ForegroundColor Red 
					$ret.Service = "Not Working Properly or Host Not Accessible"
				}
				
				
				#Write-Host "CurRelay:`t" -ForegroundColor Gray -NoNewline
				$v = Read-CurRelayFromRegistry -HostName $HostName
				if ($v -ne $null) { 
					#cleanup value for display...
					$v = $v.replace("%2e",".")
					$_v = $v.split("%")
					foreach ($__v in $_v) {
						if ($__v.length -gt 2) {
							$v = $__v.substring(2,$__v.length-4)
							break
						}
					}
					#Write-Host $v -ForegroundColor White
					$ret.CurRelay = $v
				} else { 
					#Write-Host "This setting does not exist." -ForegroundColor Red
					$ret.CurRelay = $null
				}
				
				
				#Write-Host "Relay1:`t`t" -ForegroundColor Gray -NoNewline
				$v = Get-ClientSetting -HostName $HostName -Setting "__RelayServer1" -SkipHostValidation
				if ($v.ErrorMessage -eq $null) { 
					#Write-Host $v.Value -ForegroundColor White
					$ret.Relay1 = $v.Value
				} else { 
					#Write-Host "This setting does not exist." -ForegroundColor Red
					$ret.Relay1 = $null
				}
						
				
				#Write-Host "Relay2:`t`t" -ForegroundColor Gray -NoNewline
				$v = Get-ClientSetting -HostName $HostName -Setting "__RelayServer2" -SkipHostValidation
				if ($v.ErrorMessage -eq $null) { 
					#Write-Host $v.Value -ForegroundColor White
					$ret.Relay2 = $v.Value
				} else { 
					#Write-Host "This setting does not exist." -ForegroundColor Red
					$ret.Relay2 = $null
				}
			} else {
				$ret.ErrorMessage = " Unable to Access Host"
				$msg =  "[Read-Client] :: " + $ret.ErrorMessage
				Write-Verbose $msg
			}
			
		
		}
	} #end process
	
	end {
		return $ret
	} #end end	
}

function Read-CurRelayFromRegistry {
	Param([string]$HostName)
	
	$Key = $null
	$Value = $null
	$ValuetoRetrieve = "HostSelector"
	
	Write-Verbose "[Read-CurRelayFromRegistry] :: Retrieving Registry Key"
	$Path = "SOFTWARE\Wow6432Node\BigFix\EnterpriseClient\GlobalOptions"
	try {
		$key = Get-RegistryKey -HostName $HostName -Path $Path
	} catch { 
		$key = $null
		Write-Verbose "[Read-CurRelayFromRegistry] :: Error Retrieving x64 Registry Key"
	}
	if ($key -eq $null) {
		$Path = "SOFTWARE\BigFix\EnterpriseClient\GlobalOptions"
		try {
			$key = Get-RegistryKey -HostName $HostName -Path $Path
		} catch { 
			$key = $null
			Write-Verbose "[Read-CurRelayFromRegistry] :: Error Retrieving x32 and x64 Registry Key"
		}
	}
	
	
	if ($key -ne $null) {

		$msg = "[Read-CurRelayFromRegistry] :: Retrieving Value... " + $ValuetoRetrieve
		Write-Verbose $msg
		try {
			$Value = $key.GetValue($ValuetoRetrieve)
		} catch { 
			$Value = $null 
			Write-Verbose "[Read-CurRelayFromRegistry] :: Value does not exist."
		}
	} else { 
		$Value = $null 
		Write-Verbose "[Read-CurRelayFromRegistry] :: Value does not exist."
	}#key=null
	
	
	#$msg = "[Read-CurRelayFromRegistry] :: Returning... " + $Value
	#Write-Verbose $msg
	return $Value
	
}

#endregion


#region Stop-Client
function Stop-Client {
<# 
		.Synopsis
			Stops the client service.
			
		.Description
			Confirms HostName using the Test-Host cmdlet unless this step is skipped 
			with the skipHostValidation switch.  We then pull the service via 
			Get-WmiObject cmdlet.  Once we validate it is not already stopped, we 
			stop it using the Stop-Service cmdlet.
			
		.Parameter HostName
			Hostname of the TEM Client to be Stopped.
			
		.Parameter List
			Filename of a server list.  One hostname per line.
				
		.Parameter SkipHostValidation
			Flag to speed up process by skipping the host validation step.
		
		.Example
			Stop-Client
			Description
			-----------
			Stops the Client service on the localhost.
			
		.Example
			Stop-Client DanielPC
			Stop-Client -h DanielPC
			
			C:\PS>Stop-Client -HostName DanielPC
			
			Description
			-----------
			Stops the Client service on DanielPC.
			
		.Example
			Stop-Client -l servers.txt
			C:\PS>Stop-Client -List servers.txt
			
			Description
			-----------
			Stops the Client service on the list of hosts within servers.txt
			
		.OUTPUTS
			System.Object
		
		.NOTES
			NAME:       Stop-Client
			AUTHOR:     Daniel H Moran
			LASTEDIT:   04/28/2011
			#Requires   -Version 2.0
	#>
	
	[Cmdletbinding()]
    param(
		[Parameter(
			Position = 0,
			ValueFromPipeline = $true,
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Hostname or IP address of the Client to be stopped."
			)] [Alias("h")]
		[string]$HostName = $Env:ComputerName,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Client List to pull from."
			)] [Alias("l")] [validateScript({ Test-Path $_ })]
		[string]$List,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Skip Host Validation Part."
			)]
		[switch]$SkipHostValidation		
		)
		
	begin {
		if ($List -ne "") {
			$ret = @()
		} else { 
			$ret = "" | Select HostName,Success,ErrorMessage 
			$ret.Success = $null
			$ret.ErrorMessage = $null
		}
	} #end begin
	
	
	process {
		if ($List -ne "") {
			Write-Verbose "[Stop-Client] :: List = $List"
			
			#now read whole file and search each of them for our problems...
			$hostlist = (Get-Content -Path $List)
			#$num = ($hostlist | Measure-Object).count
			#Write-Host "List contains $num hosts."

			$successCount = 0
			$failureCount = 0
			foreach($HostName in $hostlist)
			{	
				if ($HostName.trim() -ne "") {
					Write-Verbose "[Stop-Client] :: Processing $HostName"
					
					$rly = Stop-Client -HostName $HostName
								
					if (($rly.ErrorMessage -eq $null) -and ($rly.Success)) {
						$successCount++
						Write-Verbose "[Stop-Client] :: Successfully Stopped Client"
					} else {
						$failureCount++
						Write-Verbose "[Stop-Client] :: Failed to Stopped Client"
					}

					#add to object array to be returned to user
					$ret += $rly
				
				}
			}
						
			Write-Verbose "[Stop-Client] :: Hosts Successful:  $successCount"
			Write-Verbose "[Stop-Client] :: Hosts Unsuccessful:  $failureCount"
			
		} else {
			$ret.HostName = $HostName
			
			[bool]$DoIT = $true
			if (!$SkipHostValidation) { $DoIT = (Test-Host -HostName $HostName -skipShareTest) }
			if ($DoIT) {
			
				#Stop the Relay Service
				$using = "get-wmiobject"
				$service = Get-WmiObject -ErrorAction SilentlyContinue -ComputerName $HostName -Class Win32_Service | Where {$_.Name -eq "BESClient"} 
						
				#try a different way if wmi doesn't work...
				if ($service -eq $null) {
					Write-Verbose "[Stop-Client] :: Failed to Retrieve Service via WMI, trying alternative..."
					$using = "get-service"
					$service = Get-Service -ComputerName $HostName -Name "BESClient" -ErrorAction SilentlyContinue
				} else {
					Write-Verbose "[Stop-Client] :: Successfully Retrieved Service via WMI"
				}
				
				if ($service -eq $null) {
					$ret.Success = $false
					$ret.ErrorMessage = "Unable to Retrieve Service, Either Doesn't Exist or Unable to Access."
					$msg = "[Stop-Client] :: " + $ret.ErrorMessage
					Write-Verbose $msg
				} else {
					
					#if we can't use wmi, then we can't stop the service manually... if local it's ok.
					if (($using -eq "get-service") -and $HostName -ne $Env:ComputerName) {
						$ret.Success = $false
						$ret.ErrorMessage = "Unable to Retrieve Service via WMI.  (We can only stop the service if we have WMI access to the remote system.)"
						$msg = "[Stop-Client] :: " + $ret.ErrorMessage
						Write-Verbose $msg
						
					} else {
					
						#STOP THE SERVICE
						if (($service.state -eq "Running" -and $using -eq "get-wmiobject") -or ($service.status -eq "Running" -and $using -eq "get-service")) {
							#attempt to stop the service...
							Write-Verbose "[Stop-Client] :: Stopping Client Service"
							if ($using -eq "get-wmiobject") {
								$tmp = (Get-WmiObject -computer $HostName Win32_Service -Filter "Name='besclient'").InvokeMethod("StopService",$null)
							} else {
								Stop-Service -Name "BESClient" -ErrorAction SilentlyContinue
							}
						
							$timeout = 10
							while (($service.state -ne "Stopped" -and $using -eq "get-wmiobject") -or ($service.status -ne "Stopped" -and $using -eq "get-service")) {
								#re-check status of service
								if ($using -eq "get-wmiobject") {
									$service = Get-WmiObject -ErrorAction SilentlyContinue -ComputerName $HostName -Class Win32_Service | Where {$_.Name -eq "BESClient"} 
								} else {
									$service = Get-Service -ComputerName $HostName -Name "BESClient" -ErrorAction SilentlyContinue
								}
								
								sleep 2
								$timeout=$timeout-1
								if ($timeout -le 0) { break }
							}
							
							if ($timeout -le 0) {
								$ret.Success = $false
								$ret.ErrorMessage = "Timed Out trying to Stop Client Service"
								$msg =  "[Stop-Client] :: " + $ret.ErrorMessage
								Write-Verbose $msg
							} else {
								$ret.Success = $true
								Write-Verbose "[Stop-Client] :: Successfully Stopped the Client Service"
							}
						} else {
							$ret.Success = $true
							$ret.ErrorMessage = "Service Already in a Stopped State"
							Write-Verbose "[Stop-Client] :: Service Already in a Stopped State"
						}
						
						
						
					} #USING GET-SERVICE
							
				}
			} else {
				$ret.Success = $false
				$ret.ErrorMessage = " Unable to Access Host"
				$msg =  "[Stop-Client] :: " + $ret.ErrorMessage
				Write-Verbose $msg
			}
		} #LIST
	} #end process
	
	end {
		return $ret
	} #end end	
}

#endregion


#region Start-Client
function Start-Client {
<# 
		.Synopsis
			Starts the client service.
			
		.Description
			Confirms HostName using the Test-Host cmdlet unless this step is skipped 
			with the skipHostValidation switch.  We then pull the service via 
			Get-WmiObject cmdlet.  Once we validate it is not already started, we 
			start it using the Start-Service cmdlet.
			
		.Parameter HostName
			Hostname of the TEM Client to be Started.
			
		.Parameter List
			Filename of a server list.  One hostname per line.
				
		.Parameter SkipHostValidation
			Flag to speed up process by skipping the host validation step.
		
		.Example
			Start-Client
			Description
			-----------
			Starts the Client service on the localhost.
			
		.Example
			Start-Client DanielPC
			Start-Client -h DanielPC
			
			C:\PS>Start-Client -HostName DanielPC
			
			Description
			-----------
			Starts the Client service on DanielPC.
			
		.Example
			Start-Client -l servers.txt
			C:\PS>Start-Client -List servers.txt
			
			Description
			-----------
			Starts the Client service on the list of hosts within servers.txt
			
		.OUTPUTS
			System.Object
		
		.NOTES
			NAME:       Start-Client
			AUTHOR:     Daniel H Moran
			LASTEDIT:   04/28/2011
			#Requires   -Version 2.0
	#>
	
	[Cmdletbinding()]
    param(
		[Parameter(
			Position = 0,
			ValueFromPipeline = $true,
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Hostname or IP address of the Client to be started."
			)] [Alias("h")]
		[string]$HostName = $Env:ComputerName,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Client List to pull from."
			)] [Alias("l")] [validateScript({ Test-Path $_ })]
		[string]$List,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Skip Host Validation Part."
			)]
		[switch]$SkipHostValidation		
		)
		
	begin {
		if ($List -ne "") {
			$ret = @()
		} else { 
			$ret = "" | Select HostName,Success,ErrorMessage 
			$ret.Success = $null
			$ret.ErrorMessage = $null
		}
	} #end begin
	
	
	process {
		if ($List -ne "") {
			Write-Verbose "[Start-Client] :: List = $List"
			
			#now read whole file and search each of them for our problems...
			$hostlist = (Get-Content -Path $List)
			#$num = ($hostlist | Measure-Object).count
			#Write-Host "List contains $num hosts."

			$successCount = 0
			$failureCount = 0
			foreach($HostName in $hostlist)
			{	
				if ($HostName.trim() -ne "") {
					Write-Verbose "[Start-Client] :: Processing $HostName"
					
					$rly = Start-Client -HostName $HostName
								
					if (($rly.ErrorMessage -eq $null) -and ($rly.Success)) {
						$successCount++
						Write-Verbose "[Start-Client] :: Successfully Started Client"
					} else {
						$failureCount++
						Write-Verbose "[Start-Client] :: Failed to Started Client"
					}

					#add to object array to be returned to user
					$ret += $rly
				
				}
			}
						
			Write-Verbose "[Start-Client] :: Hosts Successful:  $successCount"
			Write-Verbose "[Start-Client] :: Hosts Unsuccessful:  $failureCount"
			
		} else {
			$ret.HostName = $HostName
			
			[bool]$DoIT = $true
			if (!$SkipHostValidation) { $DoIT = (Test-Host -HostName $HostName -skipShareTest) }
			if ($DoIT) {
			
				#Stop the Relay Service
				$using = "get-wmiobject"
				$service = Get-WmiObject -ErrorAction SilentlyContinue -ComputerName $HostName -Class Win32_Service | Where {$_.Name -eq "BESClient"} 
						
				#try a different way if wmi doesn't work...
				if ($service -eq $null) {
					Write-Verbose "[Start-Client] :: Failed to Retrieve Service via WMI, trying alternative..."
					$using = "get-service"
					$service = Get-Service -ComputerName $HostName -Name "BESClient" -ErrorAction SilentlyContinue
				} else {
					Write-Verbose "[Start-Client] :: Successfully Retrieved Service via WMI"
				}
				
				if ($service -eq $null) {
					$ret.Success = $false
					$ret.ErrorMessage = "Unable to Retrieve Service, Either Doesn't Exist or Unable to Access."
					$msg = "[Start-Client] :: " + $ret.ErrorMessage
					Write-Verbose $msg
				} else {
					
					#if we can't use wmi, then we can't stop the service manually... if local it's ok.
					if (($using -eq "get-service") -and $HostName -ne $Env:ComputerName) {
						$ret.Success = $false
						$ret.ErrorMessage = "Unable to Retrieve Service via WMI.  (We can only start the service if we have WMI access to the remote system.)"
						$msg = "[Start-Client] :: " + $ret.ErrorMessage
						Write-Verbose $msg
						
					} else {
					
						#START THE SERVICE
						if ($ret.ErrorMessage -eq $null) {
							#attempt to stop the service...
							Write-Verbose "[Start-Client] :: Starting Client Service"
							if ($using -eq "get-wmiobject") {
								$tmp = (Get-WmiObject -computer $HostName Win32_Service -Filter "Name='besclient'").InvokeMethod("StartService",$null)
							} else {
								Start-Service -Name "BESClient" -ErrorAction SilentlyContinue
							}
							
							$timeout = 10
							while (($service.state -ne "Running" -and $using -eq "get-wmiobject") -or ($service.status -ne "Running" -and $using -eq "get-service")) {
								#re-check status of service
								if ($using -eq "get-wmiobject") {
									$service = Get-WmiObject -ErrorAction SilentlyContinue -ComputerName $HostName -Class Win32_Service | Where {$_.Name -eq "BESClient"} 
								} else {
									$service = Get-Service -ComputerName $HostName -Name "BESClient" -ErrorAction SilentlyContinue
								}
								
								sleep 2
								$timeout=$timeout-1
								if ($timeout -le 0) { break }
							}
							
							if ($timeout -le 0) {
								$ret.Success = $false
								$ret.ErrorMessage = "Timed Out trying to Start Client Service"
								$msg =  "[Start-Client] :: " + $ret.ErrorMessage
								Write-Verbose $msg
							} else { 
								$ret.Success = $true
								Write-Verbose "[Start-Client] :: Successfully Started the Client Service"
							}
						} #$ret.ErrorMessage -eq $null
						
						
						
					} #USING GET-SERVICE
							
				}
			} else {
				$ret.Success = $false
				$ret.ErrorMessage = " Unable to Access Host"
				$msg =  "[Start-Client] :: " + $ret.ErrorMessage
				Write-Verbose $msg
			}
		} #LIST
	} #end process
	
	end {
		return $ret
	} #end end	
}

#endregion


#region Restart-Client
function Restart-Client {
<# 
		.Synopsis
			Calls Stop- then Start-Client with confirmation logic built in.
			
		.Description
			First we call the Stop-Client cmdlet, then after validating success call the Start-Client cmdlet.
			
		.Parameter HostName
			Hostname of the TEM Client to be restarted.
			
		.Parameter List
			Filename of a server list.  One hostname per line.
				
		.Parameter SkipHostValidation
			Flag to speed up process by skipping the host validation step.
		
		.Example
			Restart-Client
			Description
			-----------
			Restarts the Client service on the localhost.
			
		.Example
			Restart-Client DanielPC
			Restart-Client -h DanielPC
			
			C:\PS>Restart-Client -HostName DanielPC
			
			Description
			-----------
			Restarts the Client service on DanielPC.
			
		.Example
			Restart-Client -l servers.txt
			C:\PS>Restart-Client -List servers.txt
			
			Description
			-----------
			Restarts the Client service on the list of hosts within servers.txt
			
		.OUTPUTS
			System.Object
		
		.NOTES
			NAME:       Restart-Client
			AUTHOR:     Daniel H Moran
			LASTEDIT:   04/25/2011
			#Requires   -Version 2.0
	#>
	
	[Cmdletbinding()]
    param(
		[Parameter(
			Position = 0,
			ValueFromPipeline = $true,
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Hostname or IP address of the Client to be queried."
			)] [Alias("h")]
		[string]$HostName = $Env:ComputerName,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Client List to pull from."
			)] [Alias("l")] [validateScript({ Test-Path $_ })]
		[string]$List,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Skip Host Validation Part."
			)]
		[switch]$SkipHostValidation		
		)
		
	begin {
		if ($List -ne "") {
			$ret = @()
		} else { 
			$ret = "" | Select HostName,Success,ErrorMessage 
			$ret.Success = $null
			$ret.ErrorMessage = $null
		}
	} #end begin
	
	
	process {
		if ($List -ne "") {
			Write-Verbose "[Restart-Client] :: List = $List"
			
			#now read whole file and search each of them for our problems...
			$hostlist = (Get-Content -Path $List)
			#$num = ($hostlist | Measure-Object).count
			#Write-Host "List contains $num hosts."

			$successCount = 0
			$failureCount = 0
			foreach($HostName in $hostlist)
			{	
				if ($HostName.trim() -ne "") {
					Write-Verbose "[Restart-Client] :: Processing $HostName"
					
					$rly = Restart-Client -HostName $HostName
								
					if (($rly.ErrorMessage -eq $null) -and ($rly.Success)) {
						$successCount++
						Write-Verbose "[Restart-Client] :: Successfully Restarted Client"
					} else {
						$failureCount++
						Write-Verbose "[Restart-Client] :: Failed to Restart Client"
					}

					#add to object array to be returned to user
					$ret += $rly
				
				}
			}
						
			Write-Verbose "[Restart-Client] :: Hosts Successful:  $successCount"
			Write-Verbose "[Restart-Client] :: Hosts Unsuccessful:  $failureCount"
			
		} else {
			$ret.HostName = $HostName
			
			[bool]$DoIT = $true
			if (!$SkipHostValidation) { $DoIT = (Test-Host -HostName $HostName -skipShareTest) }
			if ($DoIT) {
				$res = Stop-Client -HostName $HostName -SkipHostValidation
				
				if ($res.Success) {
					$res = Start-Client -HostName $HostName -SkipHostValidation
					
					if ($res.Success) {
						$ret.Success = $true
						Write-Verbose "[Restart-Relay] :: Successfully Restarted Service"
					} else {
						$ret.ErrorMessage = $res.ErrorMessage
						$ret.Success = $false
						Write-Verbose "[Restart-Relay] :: Stop Successful, but Start Failed"
					}	
				} else {
					$ret.ErrorMessage = $res.ErrorMessage
					$ret.Success = $false
					Write-Verbose "[Restart-Relay] :: Failed to Stop Service"
				}
				
			} else {
				$ret.Success = $false
				$ret.ErrorMessage = " Unable to Access Host"
				$msg =  "[Restart-Client] :: " + $ret.ErrorMessage
				Write-Verbose $msg
			}
		} #LIST
	} #end process
	
	end {
		return $ret
	} #end end	
}

#endregion




################################
#CLIENT SETTINGS

#region Set-ClientSetting
function Set-ClientSetting {
	<# 
		.Synopsis
			Reaches into the registry to set or create a client setting with value and effective date.
		
		.Description
			First a HostName validation is performed using the Test-Host Cmdlet.  Then we validate the 
			32/64bit registry path to “BigFix Enterprise”.  After that we check to see if the key to 
			be set already exists using the Get-RegistryKey cmdlet then either create one using 
			New-RegistryValue or modify the value using Set-RegistryValue.  Lastly we configure the 
			effective date registry value. 
		
		.Parameter HostName
			Hostname, FQDN, or IP address of the client.
			
		.Parameter List
			List of computers to perform Set-ClientSetting on.
		
		.Parameter Setting
			Name of the client setting to be configured.
		
		.Parameter Value
			Value to be configured for this client setting.
		
		.Parameter SkipHostValidation
			This switch will speed up the confirmation process by skipping the host network connectivity check.
		
		.Example
			Set-ClientSetting DanielServer __RelayServer1 http://bigfix.moranit.com:52311/bfmirror/downloads/
			C:\PS>Set-ClientSetting -HostName DanielServer -Setting __RelayServer1 -Value http://bigfix.moranit.com:52311/bfmirror/downloads/
			
			C:\PS>Set-ClientSetting -h DanielServer -s __RelayServer1 -v http://bigfix.moranit.com:52311/bfmirror/downloads/
			
			Description
			-----------
			Configures the Client Setting on the host named DanielServer.
			
		.Example
			Set-ClientSetting -l endpoints.txt __RelayServer1 http://bigfix.moranit.com:52311/bfmirror/downloads/
			C:\PS>Set-ClientSetting -List endpoints.txt -Setting __RelayServer1 -Value http://bigfix.moranit.com:52311/bfmirror/downloads/
			
			Description
			-----------
			Configures the specified setting on all endpoints within the file endpoints.txt.
			
		.OUTPUTS
			System.Object
		
		.NOTES
			NAME:       Set-ClientSetting
			AUTHOR:     Daniel H Moran
			LASTEDIT:   04/18/2011
			#Requires   -Version 2.0
	#>
	
	[Cmdletbinding()]
    param(
		[Parameter(
			Position = 0,
			ValueFromPipeline = $true,
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Hostname or IP address of the client to be configured."
			)] [Alias("h")]
		[string]$HostName = $Env:ComputerName,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "List of clients to be configured.."
			)] [Alias("l")] [validateScript({ Test-Path $_ })]
		[string]$List,
		
		[Parameter(
			Mandatory = $true,
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Client List to be tested."
			)] [Alias("s")]
		[string]$Setting,
		
		[Parameter(
			Mandatory = $true,
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Client List to be tested."
			)] [Alias("v")]
		[string]$Value,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Skip Host Validation Part."
			)]
		[switch]$SkipHostValidation
	)
			
	begin {
		if ($List -ne "") {
			$ret = @()
		} else { $ret = "" | Select HostName,Setting,Value,EffectiveDate,ErrorMessage }
    } #begin
    
    process {
		if ($List -ne "") {
			Write-Verbose "[Set-ClientSetting] :: List = $List"
			
			#now read whole file and search each of them for our problems...
			$hostlist = (Get-Content -Path $List)
			#$num = ($hostlist | Measure-Object).count
			#Write-Host "List contains $num hosts."

			$successCount = 0
			$failureCount = 0
			foreach($HostName in $hostlist)
			{	
				if ($HostName.trim() -ne "") {
					Write-Verbose "[Set-ClientSetting] :: Processing $HostName"
					
					Write-Verbose "[Set-ClientSetting] :: Calling Set-ClientSetting -HostName $HostName -Setting $Setting -Value $Value"
					$ct = Set-ClientSetting -HostName $HostName -Setting $Setting -Value $Value
					
					if ($ct.ErrorMessage -eq $null) {
						$successCount++
						Write-Verbose "[Set-ClientSetting] :: Client Setting Successfully Configured"
					} else {
						$failureCount++
						Write-Verbose "[Set-ClientSetting] :: Client Setting Failed Configuration"
					}
					
					$ret += $ct
				}
			}
			
			Write-Verbose "[Set-ClientSetting] :: Hosts Configured Successfully:  $successCount"
			Write-Verbose "[Set-ClientSetting] :: Hosts that Failed Configuration:  $failureCount"
			
	
		} else {
		
			$ret.HostName = $HostName
			
			Write-Verbose "[Set-ClientSetting] :: Validating Host Exists and is Accessable"
			
			[bool]$DoIT = $true
			if (!$SkipHostValidation) { $DoIT = (Test-Host -HostName $HostName -skipShareTest) }
			if ($DoIT) {
			
				Write-Verbose "[Set-ClientSetting] :: Retrieving Registry Key"
				$Path = "SOFTWARE\Wow6432Node\BigFix\EnterpriseClient\Settings\Client"
				try {
					$ret.Setting = Get-RegistryKey -HostName $HostName -Path $Path
				} catch { 
					$ret.Setting = $null
					$ret.Value = $null
					$ret.EffectiveDate = $null
					$ret.ErrorMessage = "Error Retrieving x64 Registry Key"
					$errmsg = "[Set-ClientSetting] :: " + $ret.ErrorMessage
					Write-Verbose $errmsg
				}
				if ($ret.Setting -eq $null) {
					$Path = "SOFTWARE\BigFix\EnterpriseClient\Settings\Client"
					try {
						$ret.Setting = Get-RegistryKey -HostName $HostName -Path $Path
					} catch { 
						$ret.Setting = $null
						$ret.Value = $null
						$ret.EffectiveDate = $null
						$ret.ErrorMessage = "Error Retrieving x32 and x64 Registry Keys"
						$errmsg = "[Set-ClientSetting] :: " + $ret.ErrorMessage
						Write-Verbose $errmsg
					}
				}
				
				
				if ($ret.Setting -ne $null) {
					Write-Verbose "[Set-ClientSetting] :: Validate Key Exists"
					try {
						$ret.Setting = Get-RegistryKey -HostName $HostName -Path $Path\$Setting
					} catch { 
						$ret.Setting = $null 
						Write-Verbose "[Set-ClientSetting] :: Key Already Exists"
					}
					if ($ret.Setting -eq $null) {
						Write-Verbose "[Set-ClientSetting] :: Creating new Key... New-RegistryKey -HostName $HostName -Path $Path -Name $Setting"
						try {
							$ret.Setting = New-RegistryKey -HostName $HostName -Path $Path -Name $Setting
						} catch { 
							$ret.Setting = $null
							$ret.Value = $null
							$ret.EffectiveDate = $null
							$ret.ErrorMessage = "Creating new Key Unsuccessful"
							$errmsg = "[Set-ClientSetting] :: " + $ret.ErrorMessage
							Write-Verbose $errmsg
						}
						if ($ret.Setting -ne $null) {
							Write-Verbose "[Set-ClientSetting] :: Creating new Key Successful"
						}
					}
					
					if ($ret.Setting -ne $null) {
						Write-Verbose "[Set-ClientSetting] :: Retrieving Value"
						try {
							$ret.Value = $ret.Setting.GetValue("value")
						} catch { $ret.Value = $null }
						
						if ($ret.Value -eq $null) {
							try {
								Write-Verbose "[Set-ClientSetting] :: Creating new Value... value=$Value"
								$ret.Value = New-RegistryValue -HostName $HostName -Path $ret.Setting.Name -Name "value" -Value $Value -Type String 
								Write-Verbose "[Set-ClientSetting] :: Creating New Value Successful"							
								$ret.Value = $ret.Value.value
							} catch { $ret.Value = $null }
						} else {
							try {
								Write-Verbose "[Set-ClientSetting] :: Setting... value=$Value"
								$ret.Value = Set-RegistryValue -HostName $HostName -Path $ret.Setting.Name -Name "value" -Value $Value
								Write-Verbose "[Set-ClientSetting] :: Setting Value Successful"
								$ret.Value = $ret.Value.value
							} catch { $ret.Value = $null }
						}
						
						if ($ret.Value -ne $null) {
							Write-Verbose "[Set-ClientSetting] :: Format effective date value"
							#Tue, 19 Apr 2011 05:32:06 -0500
							$edate = (Get-Date -Format r).tostring().replace("GMT","-0500")
							
							
							Write-Verbose "[Set-ClientSetting] :: Validate Value Exists... effective date"
							try {
								$ret.EffectiveDate = $ret.Setting.GetValue("effective date")
							} catch { $ret.EffectiveDate = $null }
							if ($ret.EffectiveDate -eq $null) {
								Write-Verbose "[Set-ClientSetting] :: Creating new Date Value... effective date=$eDate"
								try {
									$ret.EffectiveDate = New-RegistryValue -Path $ret.Setting.Name -Name "effective date" -Value $edate -Type String -ComputerName $HostName
									Write-Verbose "[Set-ClientSetting] :: Creating New Value Successful"							
									$ret.EffectiveDate = $ret.EffectiveDate.value
								} catch { 
									$ret.EffectiveDate = $null 
									$ret.ErrorMessage = "Creating New Effective Date Value Unsuccessful"
									$errmsg = "[Set-ClientSetting] :: " + $ret.ErrorMessage
									Write-Verbose $errmsg
								}
							} else {
								Write-Verbose "[Set-ClientSetting] :: Setting... effective date=$eDate"
								try {
									$ret.EffectiveDate = Set-RegistryValue -HostName $HostName -Path $ret.Setting.Name -Name "effective date" -Value $edate
									Write-Verbose "[Set-ClientSetting] :: Setting Value Successful"
									$ret.EffectiveDate = $ret.EffectiveDate.value
								} catch { 
									$ret.EffectiveDate = $null  
									$ret.ErrorMessage = "Updating Effective Date Value Unsuccessful"
									$errmsg = "[Set-ClientSetting] :: " + $ret.ErrorMessage
									Write-Verbose $errmsg
								}
							}
						} else { 
							$ret.EffectiveDate = $null
							$ret.ErrorMessage = "Setting Value Unsuccessful"
							$errmsg = "[Set-ClientSetting] :: " + $ret.ErrorMessage
							Write-Verbose $errmsg
						}
					}
				
				
				} #key=null
			
				
			
			
			} #If host exists
		} #List
	} #process

	
	end {
		return $ret
	} #end
} 
#export-modulemember -function Test-Client
#endregion


#region Get-ClientSetting
function Get-ClientSetting {
	<# 
		.Synopsis
			Reaches into the registry to read the value of a particular client setting.
		
		.Description
			First a HostName validation is performed using the Test-Host Cmdlet.  Then we 
			validate the 32/64bit registry path to “BigFix Enterprise”.  Lastly we pull the 
			registry value for the specified Setting and return a Settings Object.
		
		.Parameter HostName
			Hostname, FQDN, or IP address of the client.
			
		.Parameter List
			List of computers to perform Get-ClientSetting on.
		
		.Parameter Setting
			Name of the client setting to be configured.
			
		.Parameter SkipHostValidation
			This switch will speed up the confirmation process by skipping the host network connectivity check.
		
		.Example
			Get-ClientSetting DanielServer __RelayServer1
			C:\PS>Get-ClientSetting -HostName DanielServer -Setting __RelayServer1
			
			C:\PS>Get-ClientSetting -h DanielServer -s __RelayServer1
			
			Description
			-----------
			Retrieves the client setting specified.
			
		.OUTPUTS
			System.Object
		
		.NOTES
			NAME:       Get-ClientSetting
			AUTHOR:     Daniel H Moran
			LASTEDIT:   04/19/2011
			#Requires   -Version 2.0
	#>
	
	[Cmdletbinding()]
    param(
		[Parameter(
			Position = 0,
			ValueFromPipeline = $true,
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Hostname or IP address of the client to be configured."
			)] [Alias("h")]
		[string]$HostName = $Env:ComputerName,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "List of clients to be configured.."
			)] [Alias("l")] [validateScript({ Test-Path $_ })]
		[string]$List,
		
		[Parameter(
			Mandatory = $true,
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Client List to be tested."
			)] [Alias("s")]
		[string]$Setting,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Skip Host Validation Part."
			)]
		[switch]$SkipHostValidation
	)
			
	begin {
		if ($List -ne "") {
			$ret = @()
		} else { $ret = "" | Select HostName,Setting,Value,EffectiveDate,ErrorMessage }
    } #begin
    
    process {
		if ($List -ne "") {
			Write-Verbose "[Get-ClientSetting] :: List = $List"
			
			#now read whole file and search each of them for our problems...
			$hostlist = (Get-Content -Path $List)
			#$num = ($hostlist | Measure-Object).count
			#Write-Host "List contains $num hosts."

			$successCount = 0
			$failureCount = 0
			foreach($HostName in $hostlist)
			{	
				if ($HostName.trim() -ne "") {
					Write-Verbose "[Get-ClientSetting] :: Processing $HostName"
					
					Write-Verbose "[Get-ClientSetting] :: Calling Get-ClientSetting -HostName $HostName -Setting $Setting"
					$ct = Get-ClientSetting -HostName $HostName -Setting $Setting
					
					if ($ct.ErrorMessage -eq $null) {
						$successCount++
						Write-Verbose "[Get-ClientSetting] :: Client Setting Successfully Retrieved"
					} else {
						$failureCount++
						Write-Verbose "[Get-ClientSetting] :: Client Setting Failed to Return"
					}
					
					$ret += $ct
				}
			}
			
			Write-Verbose "[Get-ClientSetting] :: Hosts Configured Successfully:  $successCount"
			Write-Verbose "[Get-ClientSetting] :: Hosts that Failed Configuration:  $failureCount"
			
	
		} else {
		
			$ret.HostName = $HostName
			
			Write-Verbose "[Get-ClientSetting] :: Validating Host Exists and is Accessable"
			[bool]$DoIT = $true
			if (!$SkipHostValidation) { $DoIT = (Test-Host -HostName $HostName -skipShareTest) }
			if ($DoIT) {
			
				Write-Verbose "[Get-ClientSetting] :: Retrieving Registry Key"
				$Path = "SOFTWARE\Wow6432Node\BigFix\EnterpriseClient\Settings\Client"
				try {
					Write-Verbose "[Get-ClientSetting] :: Get-RegistryKey -HostName $HostName -Path $Path"
					$ret.Setting = Get-RegistryKey -HostName $HostName -Path $Path
				} catch { 
					$ret.Setting = $null
					$ret.Value = $null
					$ret.EffectiveDate = $null
					$ret.ErrorMessage = "Error Retrieving x64 Registry Key"
					$errmsg = "[Get-ClientSetting] :: " + $ret.ErrorMessage
					Write-Verbose $errmsg
				}
				if ($ret.Setting -eq $null) {
					$Path = "SOFTWARE\BigFix\EnterpriseClient\Settings\Client"
					try {
						Write-Verbose "[Get-ClientSetting] :: Get-RegistryKey -HostName $HostName -Path $Path"
						$ret.Setting = Get-RegistryKey -HostName $HostName -Path $Path
					} catch { 
						$ret.Setting = $null
						$ret.Value = $null
						$ret.EffectiveDate = $null
						$ret.ErrorMessage = "Error Retrieving x32 and x64 Registry Keys"
						$errmsg = "[Get-ClientSetting] :: " + $ret.ErrorMessage
						Write-Verbose $errmsg
					}
				}
				
				
				if ($ret.Setting -ne $null) {
					Write-Verbose "[Get-ClientSetting] :: Get-RegistryKey -HostName $HostName -Path $Path\$Setting"
					try {
						$ret.Setting = Get-RegistryKey -HostName $HostName -Path $Path\$Setting
					} catch { 
						$ret.Setting = $null 
					}
					
					if ($ret.Setting -ne $null) {
					
						Write-Verbose "[Get-ClientSetting] :: Retrieving Value"
						try {
							$ret.Value = $ret.Setting.GetValue("value")
						} catch { 
							$ret.Value = $null 
							$ret.EffectiveDate = $null
							$ret.ErrorMessage = "Value does not exist."
							$errmsg = "[Get-ClientSetting] :: " + $ret.ErrorMessage
							Write-Verbose $errmsg
						}
						
						if ($ret.Value -ne $null) {
							Write-Verbose "[Get-ClientSetting] :: Retrieving Effective Date"
							try {
								$ret.EffectiveDate = $ret.Setting.GetValue("effective date")
							} catch { 
								$ret.EffectiveDate = $null
								$ret.ErrorMessage = "Effective Date does not exist."
								$errmsg = "[Get-ClientSetting] :: " + $ret.ErrorMessage
								Write-Verbose $errmsg
							}
						}
						
					} else { 
						$ret.Value = $null 
						$ret.EffectiveDate = $null
						$ret.ErrorMessage = "Value does not exist."
						$errmsg = "[Get-ClientSetting] :: " + $ret.ErrorMessage
						Write-Verbose $errmsg
					}
				
				
				} else {
					Write-Verbose "[Get-ClientSetting] :: ERROR Key does not Exist!"
				}
			
				
			
			
			} #If host exists
		} #List
	} #process

	
	end {
		return $ret
	} #end
} 
#export-modulemember -function Get-ClientSetting
#endregion


#region Remove-ClientSetting
function Remove-ClientSetting {
	<# 
		.Synopsis
			Removes a particular client setting from the registry.
		
		.Description
			The HostName is first checked for [network] connectivity using Test-Host 
			Cmdlet.  Then we validate the setting currently exists using the 
			Get-RegistryKey cmdlet.  Lastly we call Remove-RegistryKey to delete the 
			specified client setting. 
		
		.Parameter HostName
			Name of computer to be configured
			
		.Parameter List
			List of computers to perform Remove-ClientSetting on.
		
		.Parameter Setting
			Name of setting to be removed.
			
		.Parameter SkipHostValidation
			This switch will speed up the confirmation process by skipping the host network connectivity check.
		
		.Example
			Remove-ClientSetting DanielServer __RelayServer1
			C:\PS>Remove-ClientSetting -HostName DanielServer -Setting __RelayServer1
			
			C:\PS>Remove-ClientSetting -h DanielServer -s __RelayServer1
			
			Description
			-----------
			Removes the Client Setting on the host named DanielServer.
			
		.Example
			Remove-ClientSetting -l endpoints.txt -s __RelayServer1
			C:\PS>Remove-ClientSetting -List endpoints.txt -Setting __RelayServer1
			
			Description
			-----------
			Removes the specified setting on all endpoints within the file endpoints.txt.
			
		.OUTPUTS
			System.Object
		
		.NOTES
			NAME:       Remove-ClientSetting
			AUTHOR:     Daniel H Moran
			LASTEDIT:   04/25/2011
			#Requires   -Version 2.0
	#>
	
	[Cmdletbinding()]
    param(
		[Parameter(
			Position = 0,
			ValueFromPipeline = $true,
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Hostname or IP address of the client to be configured."
			)] [Alias("h")]
		[string]$HostName = $Env:ComputerName,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "List of clients to be configured.."
			)] [Alias("l")] [validateScript({ Test-Path $_ })]
		[string]$List,
		
		[Parameter(
			Mandatory = $true,
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Client List to be tested."
			)] [Alias("s")]
		[string]$Setting,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Skip Host Validation Part."
			)]
		[switch]$SkipHostValidation
	)
			
	begin {
		if ($List -ne "") {
			$ret = @()
		} else { $ret = "" | Select HostName,Success,ErrorMessage }
    } #begin
    
    process {
		if ($List -ne "") {
			Write-Verbose "[Remove-ClientSetting] :: List = $List"
			
			#now read whole file and search each of them for our problems...
			$hostlist = (Get-Content -Path $List)
			#$num = ($hostlist | Measure-Object).count
			#Write-Host "List contains $num hosts."

			$successCount = 0
			$failureCount = 0
			foreach($HostName in $hostlist)
			{	
				if ($HostName.trim() -ne "") {
					Write-Verbose "[Remove-ClientSetting] :: Processing $HostName"
					
					Write-Verbose "[Remove-ClientSetting] :: Calling Remove-ClientSetting -HostName $HostName -Setting $Setting"
					$ct = Remove-ClientSetting -HostName $HostName -Setting $Setting -Value $Value
					
					if ($ct.ErrorMessage -eq $null) {
						$successCount++
						Write-Verbose "[Remove-ClientSetting] :: Client Setting Successfully Configured"
					} else {
						$failureCount++
						Write-Verbose "[Remove-ClientSetting] :: Client Setting Failed Configuration"
					}
					
					$ret += $ct
				}
			}
			
			Write-Verbose "[Remove-ClientSetting] :: Hosts Configured Successfully:  $successCount"
			Write-Verbose "[Remove-ClientSetting] :: Hosts that Failed Configuration:  $failureCount"
			
	
		} else {
		
			$ret.HostName = $HostName
			
			Write-Verbose "[Remove-ClientSetting] :: Validating Host Exists and is Accessable"
			[bool]$DoIT = $true
			if (!$SkipHostValidation) { $DoIT = (Test-Host -HostName $HostName -skipShareTest) }
			if ($DoIT) {
				Write-Verbose "[Remove-ClientSetting] :: Retrieving Registry Key"
				$Path = "SOFTWARE\Wow6432Node\BigFix\EnterpriseClient\Settings\Client"
				try {
					$Key = Get-RegistryKey -HostName $HostName -Path $Path
				} catch { 
					$ret.Success = $false
					$ret.ErrorMessage = "Error Retrieving x64 Registry Key"
					$errmsg = "[Remove-ClientSetting] :: " + $ret.ErrorMessage
					Write-Verbose $errmsg
				}
				if ($Key -eq $null) {
					$Path = "SOFTWARE\BigFix\EnterpriseClient\Settings\Client"
					try {
						$Key = Get-RegistryKey -HostName $HostName -Path $Path
					} catch { 
						$ret.Success = $null
						$ret.ErrorMessage = "Error Retrieving x32 and x64 Registry Keys"
						$errmsg = "[Remove-ClientSetting] :: " + $ret.ErrorMessage
						Write-Verbose $errmsg
					}
				}
				
				
				if ($Key -ne $null) {
					Write-Verbose "[Remove-ClientSetting] :: Validate Key Exists"
					try {
						$rk = Remove-RegistryKey -HostName $HostName -Path $Path -Name $Setting
						
						$ret.Success = $true
					} catch { 
						$ret.Success = $false
						$ret.ErrorMessage = "Failed to Delete Key"
						$msg = "[Remove-ClientSetting] :: " + $ret.ErrorMessage
						Write-Verbose $msg
					}
				} #key=null
			
				
			
			
			} #If host exists
		} #List
	} #process

	
	end {
		return $ret
	} #end
} 
#export-modulemember -function Remove-ClientSetting
#endregion


#region Set-Relays
function Set-Relays {
<# 
		.Synopsis
			Stop-Client, Configure __RelayServer1 & 2 within the registry, clears the cache and Start-Client.
			
		.Description
			The HostName is first checked for [network] connectivity using Test-Host Cmdlet.  Next we call 
			the Stop-Client cmdlet and use Set-ClientSetting or Remove-ClientSetting cmdlets to configure the 
			desired settings.  We then call Remove-ClientSetting cmdlet to remove the 
			_BESClient_RelaySelect_TertiaryRelayList and _BESClient_RelaySelect_FailoverRelay values.  Lastly 
			we clear out the HostSelector value which caches the last relay used and call the Start-Client 
			cmdlet.
			
		.Parameter HostName
			Hostname of the TEM Client to be modified.
			
		.Parameter List
			Filename of a server list.  One hostname per line.
			
		.Parameter Relay1
			Configures __RelayServer1 value, if not specified it will clear this setting.
				
		.Parameter Relay2
			Configures __RelayServer2 value, if not specified it will clear this setting.
				
		.Example
			Set-Relays danielpc -Relay1 bigfix.moranit.com -Relay2 DanielServer.moranit.com
			Description
			-----------
			This will configure relay1 and relay 2.
					
		.OUTPUTS
			null

		.NOTES
			NAME:       Set-Relays
			AUTHOR:     Daniel H Moran
			LASTEDIT:   05/05/2011
			#Requires   -Version 2.0
	#>
	
	[Cmdletbinding()]
    param(
		[Parameter(
			Position = 0,
			ValueFromPipeline = $true,
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Hostname or IP address of the Client to be queried."
			)] [Alias("h")]
		[string]$HostName = $Env:ComputerName,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Client List to pull from."
			)] [Alias("l")] [validateScript({ Test-Path $_ })]
		[string]$List,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Configure __RelayServer1"
			)] [Alias("r1")]
		[string]$Relay1 = "",
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Configure __RelayServer2"
			)] [Alias("r2")]
		[string]$Relay2 = "",
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Configure RelaySelect Override Flag."
			)]
		[switch]$Force
		)
		
	begin {
		if ($List -ne "") {
			$ret = @()
		} else { 
			$ret = "" | Select HostName,Success,ErrorMessage 
			$ret.Success = $null
			$ret.ErrorMessage = $null
		}
	} #end begin
	
	
	process {
		if ($List -ne "") {
			Write-Verbose "[Set-Relays] :: List = $List"
			
			#now read whole file and search each of them for our problems...
			$hostlist = (Get-Content -Path $List)
			#$num = ($hostlist | Measure-Object).count
			#Write-Host "List contains $num hosts."

			$successCount = 0
			$failureCount = 0
			foreach($HostName in $hostlist)
			{	
				if ($HostName.trim() -ne "") {
					Write-Verbose "[Set-Relays] :: Processing $HostName"
					
					if ($Force) {
						$res = Set-Relays -HostName $HostName -Relay1 $Relay1 -Relay2 $Relay2 -Force
					} else {
						$res = Set-Relays -HostName $HostName -Relay1 $Relay1 -Relay2 $Relay2
					}
								
					if (($res.ErrorMessage -eq $null) -and ($res.Success)) {
						$successCount++
						Write-Verbose "[Set-Relays] :: Successfully Set Client Relays"
					} else {
						$failureCount++
						Write-Verbose "[Set-Relays] :: Failed to Set Client Relays"
					}

					#add to object array to be returned to user
					$ret += $rly
				
				}
			}
						
			Write-Verbose "[Set-Relays] :: Hosts Successful:  $successCount"
			Write-Verbose "[Set-Relays] :: Hosts Unsuccessful:  $failureCount"
			
		} else {
			$ret.HostName = $HostName
			
			if (Test-Host -HostName $HostName) {
				Write-Verbose "[Set-Relays] :: Successfully Validated Host"
				
				#1. Stop-Client
				$res = Stop-Client -HostName $HostName -SkipHostValidation
				if ($res.ErrorMessage -eq $null) {
					Write-Verbose "[Set-Relays] :: Successfully Stopped Client"
				} else {
					$ret.Success = $false
					$ret.ErrorMessage = "Failed to Stop Client!"
					$msg =  "[Set-Relays] :: " + $ret.ErrorMessage
					Write-Verbose $msg
				}
				
				
					
					
				#clear client settings
				if ($Relay1.trim() -ne "") {
					Write-Verbose "[Set-Relays] :: Configure __RelayServer1"
					$rs1 = Set-ClientSetting -HostName $HostName -Setting "__RelayServer1" -Value $Relay1 -SkipHostValidation
				} else {
					Write-Verbose "[Set-Relays] :: Clear __RelayServer1"
					$rs1 = Remove-ClientSetting -HostName $HostName -Setting "__RelayServer1" -SkipHostValidation
				}
				
				if ($Relay2.trim() -ne "") {
					Write-Verbose "[Set-Relays] :: Configure __RelayServer2"
					$rs2 = Set-ClientSetting -HostName $HostName -Setting "__RelayServer2" -Value $Relay2 -SkipHostValidation
				} else {
					Write-Verbose "[Set-Relays] :: Clear __RelayServer2"
					$rs2 = Remove-ClientSetting -HostName $HostName -Setting "__RelayServer2" -SkipHostValidation
				}
				
				
				Write-Verbose "[Set-Relays] :: Clear _BESClient_RelaySelect_TertiaryRelayList"
				$tl = Remove-ClientSetting -HostName $HostName -Setting "_BESClient_RelaySelect_TertiaryRelayList" -SkipHostValidation
				
				Write-Verbose "[Set-Relays] :: Clear _BESClient_RelaySelect_FailoverRelay"
				$tl = Remove-ClientSetting -HostName $HostName -Setting "_BESClient_RelaySelect_FailoverRelay" -SkipHostValidation
				
							
				
				
				#UPDATE HOSTSELECTOR
				Write-Verbose "[Set-Relays] :: Updating HostSelector..."
				Write-Verbose "[Set-Relays] :: Retrieving Registry Key"
				$Value = "HostSelector"
				$Path = "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\BigFix\EnterpriseClient\GlobalOptions"
				try {
					$k = Get-RegistryKey -HostName $HostName -Path $Path -ErrorAction SilentlyContinue
				} catch { 
					$k = $null
					$errmsg = "[Set-Relays] :: Error Retrieving x64 Registry Key"
					Write-Verbose $errmsg
				}
				if ($k -eq $null) {
					$Path = "HKEY_LOCAL_MACHINE\SOFTWARE\BigFix\EnterpriseClient\GlobalOptions"
					try {
						$k = Get-RegistryKey -HostName $HostName -Path $Path -ErrorAction SilentlyContinue
					} catch { 
						$k = $null
						$errmsg = "[Set-Relays] :: Error Retrieving x32 and x64 Registry Keys"
						Write-Verbose $errmsg
					}
				}
				if ($k -ne $null) {
					try {
						Write-Verbose "[Set-Relays] :: Attempting to Configure HostSelector"
						$newValue = "%00%00%00%1b" + $Relay1.replace(".","%2e") + "%2eM%b6%e6%2f%a1%a6%f8%07%d9%d4%00%01%00%00%07%07%00%00%00%01%00%00%00%00%00%00%00%07%0a%90%1c%02%0a%90%18%f5%0a%ff%f5%21%0a%ff%f4%12%a1%a7%00%01%a1%ac %29%a1%ac %1e"
						$v = Set-RegistryValue -HostName $HostName -Path $Path -Name $Value -Value $newValue -Type String
						Write-Verbose "[Set-Relays] :: Successful!"
					} catch { 
						Write-Verbose "[Set-Relays] :: Failed to Configure HostSelector"
					}
				}
							
				
					
				#Start Client
				$res = Start-Client -HostName $HostName -SkipHostValidation
				if ($res.ErrorMessage -eq $null) {
					$ret.Success = $true
					Write-Verbose "[Set-Relays] :: Successfully Started Client"
				} else {
					$ret.Success = $false
					$ret.ErrorMessage = "Failed to Start Client!"
					$msg =  "[Set-Relays] :: " + $ret.ErrorMessage
					Write-Verbose $msg
				}
			
			} else {
				$ret.Success = $false
				$ret.ErrorMessage = "Unable to Access Host"
				$msg =  "[Set-Relays] :: " + $ret.ErrorMessage
				Write-Verbose $msg
			}
		} #LIST
	} #end process
	
	end {
		return $ret
	} #end end	
}

#endregion



################################
#CLIENT MASTHEAD 

#region Get-Masthead
function Get-Masthead {
<# 
		.Synopsis
			Finds and parses the masthead file returning a Masthead-object.
			
		.Description
			First a HostName validation is performed using the Test-Host Cmdlet.  Then we 
			validate the 32/64bit path to “BigFix Enterprise”.  After that we read in the 
			ActionSite.afxm masthead file and convert it to an object using the 
			ConvertTo-MastheadObj cmdlet.  We extract several values from that object and 
			return to the user.
			
		.Parameter HostName
			Hostname, FQDN, or IP address of the client.
			
		.Parameter List
			List of computers to perform Get-Masthead on.
			
		.Parameter SkipHostValidation
			This switch will speed up the confirmation process by skipping the host network connectivity check.
		
		.Example
			Get-Masthead DanielPC
			Description
			-----------
			Pulls back a Masthead Object for DanielPC
			
		.OUTPUTS
			System.Object
		
		.NOTES
			NAME:       Get-Masthead
			AUTHOR:     Daniel H Moran
			LASTEDIT:   04/20/2011
			#Requires   -Version 2.0
	#>
	
	[Cmdletbinding()]
    param(
		[Parameter(
			Position = 0,
			ValueFromPipeline = $true,
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Hostname or IP address of the relay to be queried."
			)] [Alias("h")]
		[string]$HostName = $Env:ComputerName,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Relay List to pull from."
			)] [Alias("l")] [validateScript({ Test-Path $_ })]
		[string]$List,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Skip Host Validation Part."
			)]
		[switch]$SkipHostValidation		
		)
		
	begin {
		if ($List -ne "") {
			$mh = @()
		} else { 
			$mh = "" | Select HostName,Infrastructure,RemotePath,LocalPath,Masthead,ErrorMessage
			$mh.HostName = $HostName
			$mh.RemotePath = $null
			$mh.LocalPath = $null
			$mh.Infrastructure = $null
			$mh.Masthead = $null
			$mh.ErrorMessage = $null
		}
	} #end begin
	
	
	process {
		if ($List -ne "") {
			Write-Verbose "[Get-Masthead] :: List = $List"
			
			#now read whole file and search each of them for our problems...
			$hostlist = (Get-Content -Path $List)
			#$num = ($hostlist | Measure-Object).count
			#Write-Host "List contains $num hosts."

			$successCount = 0
			$failureCount = 0
			foreach($HostName in $hostlist)
			{	
				if ($HostName.trim() -ne "") {
					Write-Verbose "[Get-Masthead] :: Processing $HostName"
					Write-Verbose "[Get-Masthead] :: Calling Get-Masthead -HostName $HostName"
					$rt = Get-Masthead -HostName $HostName
					
					if ($rt.ErrorMessage -ne $null) {
						$successCount++
						Write-Verbose "[Get-Masthead] :: Successfully Retrieved Actionsite"
					} else {
						$failureCount++
						Write-Verbose "[Get-Masthead] :: Failed to Retrieve Actionsite"
					}
					
					$ret += $rt
				}
			}
			
			
			Write-Verbose "[Get-Masthead] :: Hosts Successful:  $successCount"
			Write-Verbose "[Get-Masthead] :: Hosts Unsuccessful:  $failureCount"
			
		} else {
			Write-Verbose "[Get-Masthead] :: Validating Host Exists and is Accessable"
			
			[bool]$DoIT = $true
			if (!$SkipHostValidation) { $DoIT = (Test-Host -HostName $HostName) }
			if ($DoIT) {
				[bool]$skipTestPath = $false
				$mh.LocalPath = (Read-ClientPath -HostName $HostName -SkipHostValidation).LocalPath
				if ($mh.LocalPath -ne $null) {
					$mh.LocalPath += "ActionSite.afxm"
					$lp = $mh.LocalPath.split(":",2)
					$mh.RemotePath = "\\$HostName\" + $lp[0] + "$" + $lp[1]
					
					$FoundMasthead = (Test-Path -Path $mh.RemotePath -PathType Leaf)
				} else {
					Write-Verbose "[Get-Masthead] :: Unable to retrieve Path from Registry, Assume and Test"
					$mh.LocalPath = "c:\Program Files (x86)\BigFix Enterprise\BES Client\ActionSite.afxm"
					$mh.RemotePath = "\\$HostName\c$\Program Files (x86)\BigFix Enterprise\BES Client\ActionSite.afxm"
					$FoundMasthead = (Test-Path -Path $mh.RemotePath -PathType Leaf)
					
					#64bit test failed... try 32bit path...
					if (!$FoundMasthead) {
						Write-Verbose "[Get-Masthead] :: 64bit path not valid... assuming 32bit path."
						$mh.RemotePath = "\\$HostName\c$\Program Files\BigFix Enterprise\BES Client\ActionSite.afxm"	
						$mh.LocalPath = "c:\Program Files\BigFix Enterprise\BES Client\ActionSite.afxm"
						$FoundMasthead = (Test-Path -Path $mh.RemotePath -PathType Leaf)
					}
				}
				
				#now see if the masthead file exists in the desired location
				if ($FoundMasthead) {
					Write-Verbose "[Get-Masthead] :: Masthead file exists, process further..."
					#TODO:  Add code to extract variables from the file just like we do the actionsite...
					
					#Read-in TEMRoot and TEMPort
					Write-Verbose "[Get-Masthead] :: Read in Masthead, Parse for Additional Information"
					[string]$mastheaddata = ""
					try {
						$mastheaddata = Get-Content -Path $mh.RemotePath -ErrorAction SilentlyContinue
					} catch { }

					if ($mastheaddata -ne "") {
						Write-Verbose "[Get-Masthead] :: Successfully Read in Masthead File"
						
						$mh.Masthead = ConvertTo-MastheadObj -Masthead $mastheaddata
						
						
						if ($mh.Masthead.TEMRoot -ne $null) {
							Write-Verbose "[Get-Masthead] :: Extracting from ConvertTo-MastheadObj results."
							
							#now find which infrastructure this belongs to...
							foreach ($i in $Infrastructures) {
								if ($i.TEMRoot.tolower() -eq $mh.Masthead.TEMRoot.tolower()) {
									Write-Verbose "[Get-Masthead] :: Found Infrastucture..."
									$mh.Infrastructure = $i
									break
								}
							}
							if ($mh.Infrastructure -eq $null) {
								Write-Verbose "[Get-Masthead] :: Unknown Infrastructure Constructing New Object."
								$i = "" | Select Name,TEMRoot,TEMPort
								$i.Name = "Unknown"
								$i.TEMRoot = $TEMRoot
								$i.TEMPort = $TEMPort
								$mh.Infrastructure = $i
							}
						} else {
							Write-Verbose "[Get-Masthead] :: Unable to extract using ConvertTo-MastheadObj, trying alternative."
							#now find which infrastructure this belongs to...
							foreach ($i in $Infrastructures) {
								if ( $mastheaddata.tolower().contains($i.TEMRoot.tolower()) ) {
									Write-Verbose "[Get-Masthead] :: Found Infrastucture..."
									$mh.Infrastructure = $i
									break
								}
							}
							if ($mh.Infrastructure -eq $null) {
								Write-Verbose "[Get-Masthead] :: Unknown Infrastructure Constructing New Object."
								
								$TEMRoot = $mastheaddata.split("x-fixlet-site-gather-url",2)[1].split(":",4)[2].replace("//","")
								$TEMPort = $mastheaddata.split("x-fixlet-site-gather-url",2)[1].split(":",4)[3].split("/",2)[0]
								
								$i = "" | Select Name,TEMRoot,TEMPort
								$i.Name = "Unknown"
								$i.TEMRoot = $TEMRoot
								$i.TEMPort = $TEMPort
								$mh.Infrastructure = $i
							}
						}
						
						
					} else {
						$mh.ErrorMessage = "Failed to Read in Masthead data."
						$msg = "[Get-Masthead] :: " + $mh.ErrorMessage
						Write-Verbose $msg					
					}
					
					
				} else {
					$mh.ErrorMessage = "Masthead file does not exist."
					$msg = "[Get-Masthead] :: " + $mh.ErrorMessage
					Write-Verbose $msg					
				}
			
			} else {
				$mh.ErrorMessage = "Host Not Accessible."
				$msg = "[Get-Masthead] :: " + $mh.ErrorMessage
				Write-Verbose $msg					
			}
		}
	} #end process
	
	end {
		return $mh
	} #end end	
}
#endregion


#region Set-Masthead
function Set-Masthead {
<# 
		.Synopsis
			Replaces an existing masthead with the one provided, configures Relay values and restarts the client.
			
		.Description
			First a HostName validation is performed using the Test-Host Cmdlet.  Next we call the 
			Stop-Client cmdlet and retrieve the path object via Read-ClientPath.  After testing the 
			path returned, we backup the original masthead file and copy the new one into place.  
			We then update the __RelayServer1/2 values and clear the 
			_BESClient_RelaySelect_TertiaryRelayList and HostSelector values.  Lastly we start the 
			client back up using the Start-Client cmdlet.
			
		.Parameter HostName
			Hostname, FQDN, or IP address of the client.
			
		.Parameter List
			List of computers to perform Set-Masthead on.
			
		.Parameter Masthead
			Path to the new Masthead file.
			
		.Parameter Relay1
			Configures __RelayServer1 value, if not specified it will clear this setting.
				
		.Parameter Relay2
			Configures __RelayServer2 value, if not specified it will clear this setting.
				
		.Example
			Set-Masthead -mh c:\masthead.afxm
			Description
			-----------
			Copies a new masthead file to the local host, clears settings and restarts client.
			
		.Example
			Set-Masthead DanielPC -mh c:\masthead.afxm
			Set-Masthead -h DanielPC -mh c:\masthead.afxm
			
			C:\PS>Set-Masthead -HostName DanielPC
			
			Description
			-----------
			Copies a new masthead file to DanielPC, clears settings and restarts client.
			
		.Example
			Set-Masthead -l servers.txt -mh c:\masthead.afxm
			C:\PS>Set-Masthead -List servers.txt -mh c:\masthead.afxm
			
			Description
			-----------
			Copies the new masthead file to a list of servers, clears settings and restarts each client.
			
		.OUTPUTS
			null
		
		.NOTES
			NAME:       Set-Masthead
			AUTHOR:     Daniel H Moran
			LASTEDIT:   04/25/2011
			#Requires   -Version 2.0
	#>
	
	[Cmdletbinding()]
    param(
		[Parameter(
			Position = 0,
			ValueFromPipeline = $true,
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Hostname or IP address of the Client to be queried."
			)] [Alias("h")]
		[string]$HostName = $Env:ComputerName,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Client List to pull from."
			)] [Alias("l")] [validateScript({ Test-Path $_ })]
		[string]$List,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "New Masthead file."
			)] [Alias("mh")] [validateScript({ Test-Path $_ })]
		[string]$Masthead,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Configure __RelayServer1"
			)] [Alias("r1")]
		[string]$Relay1 = "",
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Configure __RelayServer2"
			)] [Alias("r2")]
		[string]$Relay2 = ""
		)
		
	begin {
		if ($List -ne "") {
			$ret = @()
		} else { 
			$ret = "" | Select HostName,NewMasthead,CurMasthead,OldMasthead,Success,ErrorMessage 
			$ret.NewMasthead = $null
			$ret.CurMasthead = $null
			$ret.OldMasthead = $null
			$ret.Success = $null
			$ret.ErrorMessage = $null
		}
	} #end begin
	
	
	process {
		if ($List -ne "") {
			Write-Verbose "[Set-Masthead] :: List = $List"
			
			#now read whole file and search each of them for our problems...
			$hostlist = (Get-Content -Path $List)
			#$num = ($hostlist | Measure-Object).count
			#Write-Host "List contains $num hosts."

			$successCount = 0
			$failureCount = 0
			foreach($HostName in $hostlist)
			{	
				if ($HostName.trim() -ne "") {
					Write-Verbose "[Set-Masthead] :: Processing $HostName"
					
					if ($Force) {
						$res = Set-Masthead -HostName $HostName -Masthead $Masthead -Force
					} else {
						$res = Set-Masthead -HostName $HostName -Masthead $Masthead
					}
								
					if (($res.ErrorMessage -eq $null) -and ($res.Success)) {
						$successCount++
						Write-Verbose "[Set-Masthead] :: Successfully Reset Client Masthead"
					} else {
						$failureCount++
						Write-Verbose "[Set-Masthead] :: Failed to Reset Client Masthead"
					}

					#add to object array to be returned to user
					$ret += $rly
				
				}
			}
						
			Write-Verbose "[Set-Masthead] :: Hosts Successful:  $successCount"
			Write-Verbose "[Set-Masthead] :: Hosts Unsuccessful:  $failureCount"
			
		} else {
			$ret.HostName = $HostName
			$ret.NewMasthead = $Masthead
			if (Test-Host -HostName $HostName) {
				Write-Verbose "[Set-Masthead] :: Successfully Validated Host"
				
				#1. Stop-Client
				$res = Stop-Client -HostName $HostName -SkipHostValidation
				if ($res.ErrorMessage -eq $null) {
					Write-Verbose "[Set-Masthead] :: Successfully Stopped Client"
				} else {
					$ret.Success = $false
					$ret.ErrorMessage = "Failed to Stop Client!"
					$msg =  "[Set-Masthead] :: " + $ret.ErrorMessage
					Write-Verbose $msg
				}
				
				
				
				#pull client path information from registry...
				$path = Read-ClientPath -HostName $HostName -SkipHostValidation
				if ($Path.ErrorMessage -eq $null) {
				
					
					
					
					Write-Verbose "[Set-Masthead] :: Successfully Retrieved Path Information"
					$ret.CurMasthead = $Path.RemotePath + "actionsite.afxm"
				
					if (Test-Path -Path $ret.CurMasthead -PathType Leaf) {
						Write-Verbose "[Set-Masthead] :: Successfully Confirmed Current Masthead File"
						#rename and set oldMasthead
						$ret.OldMasthead = $Path.RemotePath + "_actionsite.afxm"
						
						Write-Verbose "[Set-Masthead] :: Moving Current Masthead to Old Masthead Position"
						$mi = Move-Item -Path $ret.CurMasthead -Destination $ret.OldMasthead -Force
						
						if (Test-Path -Path $ret.OldMasthead -PathType Leaf) {
							Write-Verbose "[Set-Masthead] :: Successfully Confirmed Backup Masthead File"
																	
							#copy new masthead out to endpoint
							Write-Verbose "[Set-Masthead] :: Copying New Masthead out to Endpoint"
							$ci = Copy-Item -Path $Masthead -Destination $ret.CurMasthead -Force
						
							if (Test-Path -Path $ret.CurMasthead -PathType Leaf) {
								Write-Verbose "[Set-Masthead] :: Successfully New Masthead File."
								
								#clear client settings
								if ($Relay1.trim() -ne "") {
									Write-Verbose "[Set-Masthead] :: Configure __RelayServer1"
									$rs1 = Set-ClientSetting -HostName $HostName -Setting "__RelayServer1" -Value $Relay1 -SkipHostValidation
								} else {
									Write-Verbose "[Set-Masthead] :: Clear __RelayServer1"
									$rs1 = Remove-ClientSetting -HostName $HostName -Setting "__RelayServer1" -SkipHostValidation
								}
								
								if ($Relay2.trim() -ne "") {
									Write-Verbose "[Set-Masthead] :: Configure __RelayServer2"
									$rs2 = Set-ClientSetting -HostName $HostName -Setting "__RelayServer2" -Value $Relay2 -SkipHostValidation
								} else {
									Write-Verbose "[Set-Masthead] :: Clear __RelayServer2"
									$rs2 = Remove-ClientSetting -HostName $HostName -Setting "__RelayServer2" -SkipHostValidation
								}
								
								Write-Verbose "[Set-Masthead] :: Clear _BESClient_RelaySelect_TertiaryRelayList"
								$tl = Remove-ClientSetting -HostName $HostName -Setting "_BESClient_RelaySelect_TertiaryRelayList" -SkipHostValidation
								
								
								
								#UPDATE HOSTSELECTOR
								Write-Verbose "[Set-Masthead] :: Updating HostSelector..."
								Write-Verbose "[Set-Masthead] :: Retrieving Registry Key"
								$Value = "HostSelector"
								$Path = "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\BigFix\EnterpriseClient\GlobalOptions"
								try {
									$k = Get-RegistryKey -HostName $HostName -Path $Path -ErrorAction SilentlyContinue
								} catch { 
									$k = $null
									$errmsg = "[Set-Masthead] :: Error Retrieving x64 Registry Key"
									Write-Verbose $errmsg
								}
								if ($k -eq $null) {
									$Path = "HKEY_LOCAL_MACHINE\SOFTWARE\BigFix\EnterpriseClient\GlobalOptions"
									try {
										$k = Get-RegistryKey -HostName $HostName -Path $Path  -ErrorAction SilentlyContinue
									} catch { 
										$k = $null
										$errmsg = "[Set-Masthead] :: Error Retrieving x32 and x64 Registry Keys"
										Write-Verbose $errmsg
									}
								}
								if ($k -ne $null) {
									try {
										Write-Verbose "[Set-Masthead] :: Attempting to Configure HostSelector"
										$newValue = "%00%00%00%1b" + $Relay1.replace(".","%2e") + "%2eM%b6%e6%2f%a1%a6%f8%07%d9%d4%00%01%00%00%07%07%00%00%00%01%00%00%00%00%00%00%00%07%0a%90%1c%02%0a%90%18%f5%0a%ff%f5%21%0a%ff%f4%12%a1%a7%00%01%a1%ac %29%a1%ac %1e"
										$v = Set-RegistryValue -HostName $HostName -Path $Path -Name $Value -Value $newValue -Type String
										Write-Verbose "[Set-Masthead] :: Successful!"
									} catch { 
										Write-Verbose "[Set-Masthead] :: Failed to Configure HostSelector"
									}
								}
								
								
							} else {
								$ret.Success = $false
								$ret.ErrorMessage = "Write Failure... Unable to Copy New Masthead out to Endpoint."
								$msg =  "[Set-Masthead] :: " + $ret.ErrorMessage
								Write-Verbose $msg
							}		
							
						
						} else {
							$ret.Success = $false
							$ret.ErrorMessage = "Write Failure... Unable to Backup Current Masthead."
							$msg =  "[Set-Masthead] :: " + $ret.ErrorMessage
							Write-Verbose $msg
						}		
						
					
					} else {
						$ret.Success = $false
						$ret.ErrorMessage = "Current Masthead Path Can Not be Confirmed."
						$msg =  "[Set-Masthead] :: " + $ret.ErrorMessage
						Write-Verbose $msg
					}
					
					
					
					
					#wipe out cache info...
					Write-Verbose "[Clear-ClientCache] :: Removing Cache Now..."
					$cache = $Path.RemotePath + "__BESData"
					$res = Remove-Item -Path $cache -Recurse -Force -ErrorAction SilentlyContinue
											
					
					
					
				} else {
					$ret.Success = $false
					$ret.ErrorMessage = $Path.ErrorMessage
					$msg =  "[Set-Masthead] :: " + $ret.ErrorMessage
					Write-Verbose $msg
				}
					
					
				#Start Client
				$res = Start-Client -HostName $HostName -SkipHostValidation
				if ($res.ErrorMessage -eq $null) {
					Write-Verbose "[Set-Masthead] :: Successfully Started Client"
				} else {
					$ret.Success = $false
					$ret.ErrorMessage = "Failed to Start Client!"
					$msg =  "[Set-Masthead] :: " + $ret.ErrorMessage
					Write-Verbose $msg
				}
			
			} else {
				$ret.Success = $false
				$ret.ErrorMessage = "Unable to Access Host"
				$msg =  "[Set-Masthead] :: " + $ret.ErrorMessage
				Write-Verbose $msg
			}
		} #LIST
	} #end process
	
	end {
		return $ret
	} #end end	
}

#endregion


#region ConvertTo-MastheadObj
function ConvertTo-MastheadObj {
	<# 
		.Synopsis
			Parses a masthead file and returns a Masthead-object.
		
		.Description
			Receives the masthead file contents, loops through and extracts the vital pieces of 
			information to construct a Masthead Object that is returned.
		
		.Parameter Masthead
			String containing a TEM Masthead
		
		.Example
			ConvertTo-MastheadObj masthead_as_string
			C:\PS>ConvertTo-MastheadObj -mh masthead_as_string
			
			Description
			-----------
			Receives the masthead string and returns an Masthead object.
			
		.OUTPUTS
			System.Object
		
		.NOTES
			NAME:       ConvertTo-MastheadObj
			AUTHOR:     Daniel H Moran
			LASTEDIT:   04/25/2011
			#Requires   -Version 2.0
	#>
	
	[Cmdletbinding()]
    param(
		[Parameter(
			Position = 0,
			ValueFromPipeline = $true,
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "TEM Masthead as a string value."
			)] [Alias("mh")]
		[string]$Masthead
		)
   
	
	begin {
		$ret = "" | Select MIMEVersion,ContentType,TEMRoot,TEMPort,Version,Organization,LicenseAllocation,LicenseExpiration,ContactEmail,SerialNumber,UpdateFrequency,LockController,LockInitial,LockOmitSite
		
		$ret.MIMEVersion = $null
		$ret.ContentType = $null
		$ret.TEMRoot = $null
		$ret.TEMPort = $null
		$ret.Version = $null
		$ret.Organization = $null
		$ret.LicenseAllocation = $null
		$ret.LicenseExpiration = $null
		$ret.ContactEmail = $null
		$ret.SerialNumber = $null
		$ret.UpdateFrequency = $null
		$ret.LockController = $null
		$ret.LockInitial = $null
		$ret.LockOmitSite = $null
		
		
		$initialboundary = ""
		$boundary = ""
		$insideguts = $false
		$ProcessingActions = $false
		$newAction = $null
    } #begin
    
    process {
		#Write-Verbose "[ConvertTo-ActionSiteObj] :: "
		$lines = $Masthead.split("`n")
		
		Write-Verbose $lines.count
		
		foreach ($line in $lines) {
			if ($initialboundary -eq "") {
				if ($line.tolower().contains("boundary")) {
					Write-Verbose "[ConvertTo-MastheadObj] :: Found Initial Boundary Definition Line"
					$itms = $line.split(";")
					foreach($itm in $itms) {
						if ($itm.tolower().contains("boundary")) {
							if ($itm.contains("=")) { $itm = $itm.split("=",2)[1].trim() }
							if ($itm.contains('"')) { $itm = $itm.replace('"',"").trim() }
							$itm = $itm.split(" ",2)[0]
							$msg = "[ConvertTo-MastheadObj] :: Initial Boundary = " + $itm
							Write-Verbose $msg
							$initialboundary = $itm
						}
					}
				}			
			} else {
			
			
				if (!$insideguts -and $line.trim().contains("--" + $initialboundary)) { 
					Write-Verbose "[ConvertTo-MastheadObj] :: Found Start of Initial Boundary"
					$insideguts = $true 
				} elseif ($insideguts -and $line.trim().contains("--" + $initialboundary + "--")) { 
					Write-Verbose "[ConvertTo-MastheadObj] :: Found End of Initial Boundary"
					$insideguts = $false
				} elseif ($insideguts) {
				
					if (!$ProcessingActions) {
						#Write-Verbose $line
					
						#grab header info...
						if ($line.tolower().contains("x-fixlet-site-gather-url:")) {
							$ret.TEMRoot = $line.split(":",4)[2].replace("//","")
							$ret.TEMPort = $line.split(":",4)[3].split("/",2)[0]
					
						} elseif ($line.tolower().contains("mime-version:")) { 
							$ret.MIMEVersion = $line.split(":",2)[1].trim() 
						} elseif ($line.tolower().contains("content-type:")) { 
							$ret.ContentType = $line.split(";",2)[0].split(":",2)[1].trim() 
						} elseif ($line.tolower().contains("licenseallocation:")) { 
							$ret.LicenseAllocation = $line.split(":",2)[1].trim() 
						} elseif ($line.tolower().contains("licenseexpiration:")) { 
							$ret.LicenseExpiration = $line.split(":",2)[1].trim() 
						} elseif ($line.tolower().contains("from:")) { 
							$ret.ContactEmail = $line.split(":",2)[1].trim()
						} elseif ($line.tolower().contains("x-fixlet-site-masthead-version:")) { 
							$ret.Version = $line.split(":",2)[1].trim()
						} elseif ($line.tolower().contains("x-fixlet-site-serial-number:")) { 
							$ret.SerialNumber = $line.split(":",2)[1].trim()
						} elseif ($line.tolower().contains("x-fixlet-site-update-frequency:")) { 
							$ret.UpdateFrequency = $line.split(":",2)[1].trim()
						} elseif ($line.tolower().contains("x-bes-action-lock-controller:")) { 
							$ret.LockController = $line.split(":",2)[1].trim() 
						} elseif ($line.tolower().contains("x-bes-action-lock-initial:")) { 
							$ret.LockInitial = $line.split(":",2)[1].trim() 
						}elseif ($line.tolower().contains("x-bes-action-lock-omit-site:")) { 
							$ret.LockOmitSite = $line.split(":",2)[1].trim() 
						}
						
						
					} #!$ProcessingActions)

				

				} #insideguts
							
				
				
			} #initialboundary
		}
		
		

	} #process

	
	end {
		return $ret
	} #end
} 
#export-modulemember -function ConvertTo-MastheadObj
#endregion




################################
#MISC CLIENT FUNCTIONS

#region Clear-ClientCache
function Clear-ClientCache {
<# 
		.Synopsis
			Removes the BESClient Cache Directory and Restarts Client..
			
		.Description
			First a HostName validation is performed using the Test-Host Cmdlet.  
			Then uses Read-ClientPath to determine the endpoints BES Client folder 
			in order to call Remove-Item on the __BESData directory.
			
		.Parameter HostName
			Hostname, FQDN, or IP address of the client.
			
		.Parameter List
			List of computers to perform Clear-ClientCache on.
				
		.Parameter SkipHostValidation
			This switch will speed up the confirmation process by skipping the host network connectivity check.
		
		.Example
			Clear-ClientCache
			Description
			-----------
			Clears the cache on the localhost.
			
		.Example
			Clear-ClientCache DanielPC
			Clear-ClientCache -h DanielPC
			
			C:\PS>Clear-ClientCache -HostName DanielPC
			
			Description
			-----------
			Clears the cache on DanielPC.
			
		.Example
			Clear-ClientCache -l servers.txt
			C:\PS>Clear-ClientCache -List servers.txt
			
			Description
			-----------
			Clears the cache on the list of hosts within servers.txt
			
		.OUTPUTS
			System.Object
		
		.NOTES
			NAME:       Clear-ClientCache
			AUTHOR:     Daniel H Moran
			LASTEDIT:   04/28/2011
			#Requires   -Version 2.0
	#>
	
	[Cmdletbinding()]
    param(
		[Parameter(
			Position = 0,
			ValueFromPipeline = $true,
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Hostname or IP address of the Client to be cleared."
			)] [Alias("h")]
		[string]$HostName = $Env:ComputerName,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Client List to pull from."
			)] [Alias("l")] [validateScript({ Test-Path $_ })]
		[string]$List,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Skip Host Validation Part."
			)]
		[switch]$SkipHostValidation		
		)
		
	begin {
		if ($List -ne "") {
			$ret = @()
		} else { 
			$ret = "" | Select HostName,Success,ErrorMessage 
			$ret.Success = $null
			$ret.ErrorMessage = $null
		}
	} #end begin
	
	
	process {
		if ($List -ne "") {
			Write-Verbose "[Clear-ClientCache] :: List = $List"
			
			#now read whole file and search each of them for our problems...
			$hostlist = (Get-Content -Path $List)
			#$num = ($hostlist | Measure-Object).count
			#Write-Host "List contains $num hosts."

			$successCount = 0
			$failureCount = 0
			foreach($HostName in $hostlist)
			{	
				if ($HostName.trim() -ne "") {
					Write-Verbose "[Clear-ClientCache] :: Processing $HostName"
					
					$rly = Clear-ClientCache -HostName $HostName
								
					if (($rly.ErrorMessage -eq $null) -and ($rly.Success)) {
						$successCount++
						Write-Verbose "[Clear-ClientCache] :: Successfully Cleared Client Cache"
					} else {
						$failureCount++
						Write-Verbose "[Clear-ClientCache] :: Failed to Clear Client Cache"
					}

					#add to object array to be returned to user
					$ret += $rly
				
				}
			}
						
			Write-Verbose "[Clear-ClientCache] :: Hosts Successful:  $successCount"
			Write-Verbose "[Clear-ClientCache] :: Hosts Unsuccessful:  $failureCount"
			
		} else {
			$ret.HostName = $HostName
			
			[bool]$DoIT = $true
			if (!$SkipHostValidation) { $DoIT = (Test-Host -HostName $HostName -skipShareTest) }
			if ($DoIT) {
				
				
				
				#pull client path information from registry...
				$path = Read-ClientPath -HostName $HostName -SkipHostValidation
				if ($Path.ErrorMessage -eq $null) {
					$res = Stop-Client -HostName $HostName -SkipHostValidation
				
					if ($res.ErrorMessage -eq $null) {
						
						#wipe out cache info...
						Write-Verbose "[Clear-ClientCache] :: Removing Cache Now..."
						$cache = $Path.RemotePath + "__BESData"
						$res = Remove-Item -Path $cache -Recurse -Force -ErrorAction SilentlyContinue
												
						
						
						$res = Start-Client -HostName $HostName -SkipHostValidation
						if ($res.ErrorMessage -eq $null) {
							Write-Verbose "[Clear-ClientCache] :: Started Client Successfull"
							$ret.Success = $true
						} else {
							$ret.Success = $false
							$ret.ErrorMessage = "Failed to Stop BESClient... Unable to Proceed."
							$msg =  "[Clear-ClientCache] :: " + $ret.ErrorMessage
							Write-Verbose $msg
						}
						
					} else {
						$ret.Success = $false
						$ret.ErrorMessage = "Failed to Stop BESClient... Unable to Proceed."
						$msg =  "[Clear-ClientCache] :: " + $ret.ErrorMessage
						Write-Verbose $msg
					}	
					
					
				} else {
					$ret.Success = $false
					$ret.ErrorMessage = $Path.ErrorMessage
					$msg =  "[Clear-ClientCache] :: " + $ret.ErrorMessage
					Write-Verbose $msg
				}
				
				
								
			} else {
				$ret.Success = $false
				$ret.ErrorMessage = " Unable to Access Host"
				$msg =  "[Clear-ClientCache] :: " + $ret.ErrorMessage
				Write-Verbose $msg
			}
		} #LIST
	} #end process
	
	end {
		return $ret
	} #end end	
}

#endregion


#region Read-ClientPath
function Read-ClientPath {
<# 
		.Synopsis
			Reads the registry and returns a Path object containing the remote and local paths to the client service.
			
		.Description
			First a HostName validation is performed using the Test-Host Cmdlet, if it is not skipped.  
			Then we validate the 32/64bit registry path to “EnterpriseClient”.  Lastly we return the 
			client setting object for EnterpriseClientFolder.
			
		.Parameter HostName
			Hostname, FQDN, or IP address of the client.
			
		.Parameter SkipHostValidation
			This switch will speed up the confirmation process by skipping the host network connectivity check.
		
		.Example
			Read-ClientPath
			Description
			-----------
			Reads the localhost registry for where the TEM Client is installed.
			
		.Example
			Read-ClientPath DanielPC
			C:\PS>Read-ClientPath -HostName DanielPC
			
			Description
			-----------
			Reads the DanielPC registry for where the TEM Client is installed.
			
		.OUTPUTS
			System.String
		
		.NOTES
			NAME:       Read-ClientPath
			AUTHOR:     Daniel H Moran
			LASTEDIT:   04/25/2011
			#Requires   -Version 2.0
	#>
	
	[Cmdletbinding()]
	param(
		[Parameter(
			Position = 0,
			ValueFromPipeline = $true,
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Hostname or IP address of the Client to be queried."
			)] [Alias("h")]
		[string]$HostName = $Env:ComputerName,
		
		[Parameter(
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Skip Host Validation Part."
			)]
		[switch]$SkipHostValidation
		)
		
	begin {
		$ret = "" | Select HostName,Key,RemotePath,LocalPath,ErrorMessage
		$ret.Key = $null
		$ret.LocalPath = $null
		$ret.RemotePath = $null
		$ret.ErrorMessage = $null
		$ValuetoRetrieve = "EnterpriseClientFolder"
	}
	
	process {
		$ret.HostName = $HostName
		
		[bool]$DoIT = $true
		if (!$SkipHostValidation) { $DoIT = (Test-Host -HostName $HostName -skipShareTest) }
		if ($DoIT) {
			Write-Verbose "[Read-ClientPath] :: Retrieving Registry Key"
			$Path = "SOFTWARE\Wow6432Node\BigFix\EnterpriseClient"
			try {
				$ret.Key = Get-RegistryKey -HostName $HostName -Path $Path
			} catch { 
				$ret.Key = $null
				Write-Verbose "[Read-ClientPath] :: Error Retrieving x64 Registry Key"
			}
			if ($ret.Key -eq $null) {
				$Path = "SOFTWARE\BigFix\EnterpriseClient"
				try {
					$ret.Key = Get-RegistryKey -HostName $HostName -Path $Path
				} catch { 
					$ret.Key = $null
					Write-Verbose "[Read-ClientPath] :: Error Retrieving x32 and x64 Registry Key"
				}
			}
			
			
			if ($ret.Key -ne $null) {
				
				Write-Verbose "[Read-ClientPath] :: Retrieving Value"
				try {
					$ret.LocalPath = $ret.Key.GetValue($ValuetoRetrieve)
					
					$lp = $ret.LocalPath.split(":",2)
					$ret.RemotePath = "\\$HostName\" + $lp[0] + "$" + $lp[1]
				} catch {
					try {
						Write-Verbose "[Read-ClientPath] :: Default Var Missing, trying a client setting."
						$Path += "\Settings\Client\_BESClient_UploadManager_BufferDirectory"
						
						$ret.Key = Get-RegistryKey -HostName $HostName -Path $Path
						
						try {
							$_LocalPath = $ret.Key.GetValue("value")
							if (($_LocalPath -ne "") -and ($_LocalPath.contains("\__"))) {
								$ret.LocalPath = $_LocalPath.Split("_")[0]
								$lp = $ret.LocalPath.split(":",2)
								$ret.RemotePath = "\\$HostName\" + $lp[0] + "$" + $lp[1]
							}
						} catch {
							$ret.ErrorMessage = "Value does not exist."
							$msg = "[Read-ClientPath] :: " + $ret.ErrorMessage
							Write-Verbose $msg
						}
					} catch {
						$ret.ErrorMessage = "Value does not exist."
						$msg = "[Read-ClientPath] :: " + $ret.ErrorMessage
						Write-Verbose $msg
					}
				}
				
				
			} else { 
				$ret.ErrorMessage = "Key does not exist."
				$msg = "[Read-ClientPath] :: " + $ret.ErrorMessage
				Write-Verbose $msg
			}#key=null
		} else { 
			$ret.ErrorMessage = "Host does not exist."
			$msg = "[Read-ClientPath] :: " + $ret.ErrorMessage
			Write-Verbose $msg
		}
	}
	
	end {	
		$msg = "[Read-ClientPath] :: Returning... " + $ret.Value
		Write-Verbose $msg

		return $ret
	}
	
}
#endregion





















